package net.hserver.apm.plugin.sql;


import javassist.*;
import cn.hserver.core.queue.HServerQueue;
import cn.hserver.core.server.context.ConstConfig;
import cn.hserver.core.server.context.HServerContextHolder;
import cn.hserver.core.server.context.Webkit;
import net.hserver.apm.common.DataConfig;
import net.hserver.apm.common.entity.SqlInfo;

public class SqlMonitor {

    /**
     * 修改底层源码，让其回调自己
     */
    public static void modify() {
        ClassPool cp = ClassPool.getDefault();
        cp.importPackage("com.mysql.cj");
        try {
            String strPath = "com.mysql.cj.jdbc.ClientPreparedStatement";
            CtClass ctClass = cp.getCtClass(strPath);
            ctClass.freeze();
            ctClass.defrost();
            CtMethod ms = ctClass.getDeclaredMethod(
                    "execute");
            ms.addLocalVariable("beginTime", CtClass.longType);
            String before = "beginTime=System.currentTimeMillis();";
            ms.insertBefore(before);
            ms.insertAfter("{\n" +
                    "            String sql = ((PreparedQuery) this.query).getOriginalSql();\n" +
                    "sql=sql.replaceAll(\"\\\\n\",\"\");" +
                    "            QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();\n" +
                    "            for (int i =0; i < bindings.getBindValues().length; i++ ) sql = sql.replaceFirst(\"\\\\?\", new String(bindings.getBindValues()[i].getByteValue()));\n" +
                    "            net.hserver.apm.plugin.sql.SqlMonitor.sendSql(sql,beginTime);\n" +
                    "        }");

            ctClass.toClass();
            ctClass.detach();

        } catch (Throwable var9) {
            var9.printStackTrace();
        }
    }

    public static void sendSql(String sql, long beginTime) {
        Webkit webKit = HServerContextHolder.getWebKit();
        if (webKit != null) {
            long l = System.currentTimeMillis() - beginTime;
            String requestId = webKit.httpRequest.getRequestId();
            SqlInfo sqlInfo = new SqlInfo();
            sqlInfo.setAppName(ConstConfig.APP_NAME);
            sqlInfo.setChainId(requestId);
            sqlInfo.setSql(sql);
            sqlInfo.setMs((int) l);
            sqlInfo.setTime(System.currentTimeMillis());
            sqlInfo.setThreadName(Thread.currentThread().getName());
            HServerQueue.sendQueue("APM_SEND", DataConfig.APM_DATA_SQL_INFO, sqlInfo);
        }
    }
}